package com.secsys.action.price;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;

import com.secsys.action.BaseAction;
import com.secsys.dto.AssistDto;
import com.secsys.dto.StoStockDTO;
import com.secsys.dto.StoStockdailyDTO;
import com.secsys.model.TbStoCapitalization;
import com.secsys.model.TbStoFinanceprofit;
import com.secsys.model.TbStoStock;
import com.secsys.model.TbStoStockdaily;
import com.secsys.service.StoCapitalizationService;
import com.secsys.service.StoFinanceProfitService;
import com.secsys.service.StoStockService;
import com.secsys.service.StoStockdailyService;
import com.secsys.util.DateFormatUtils;

public class AdvSearchAction extends BaseAction<AssistDto>{
	/**
	 * 
	 */
	private static final long serialVersionUID = -5439359080586742110L;
	private AssistDto assistDto;
	/**
	 * <pre>
	 * stockType股票所属市场：深市、沪市、创业板;
	 * sylType市盈率类型：一年平均市盈率 、两年平均市盈率 、三年平均市盈率
	 * sylUpdown：市盈率的类型，大于、小于
	 *  syl：市盈率值</pre>
	 */
	private String stockType;
	private String sylType;
	private String sylUpdown;
	private String syl;
	private String pageStartDate;
	private String pageEndDate; 
	private String pageRate; 
	 
	private StoStockdailyService dailyService;
	private StoStockService stockService;
	
	//净利润
	private StoFinanceProfitService financeProfitService;
	//总股本
	private StoCapitalizationService capitalizationService;
	
	//保存临时总数据
	private List<StoStockDTO> finalStockList;
	private HashMap<Integer, Double> sylMap;
	private HashMap<Integer, Double> priceFloatMap;
	
	
	private String pagePriceSort;
	private String pageSylSort;
	//每页显示10条数据
	private final int limit=10;
	//供页面显示的，股票基本信息
	private List<StoStockDTO> pageStockList;
	//供页面显示的，股票ID，股票价格波动（百分比，比如20.5则为20.5%）
	private TreeMap<Integer, Double> pagePriceFloatMap;
	//供页面显示的，市盈率的map<股票ID，市盈率大小>
	private TreeMap<Integer, Double> pageSylMap;
	
	public String advSearch() throws Exception{
		if (assistDto==null || "".equals(assistDto)) {
			assistDto=new AssistDto();
			System.out.println("assistDto == null");
		}
//		String startDate=DateFormatUtils.convertDateToString(assistDto.getStartDate());
//		String endDate=DateFormatUtils.convertDateToString(assistDto.getEndDate()) ;
		String startDate=pageStartDate;
		String endDate=pageEndDate ;
		System.out.println("股票板块stockType=="+stockType+"开始时间"+startDate	+";结束时间="+endDate
				+";股票涨跌类型="+assistDto.getUpdown()+";股价涨跌百分比="+assistDto.getRate()
				+"；市盈率类型sylType="+sylType+";市盈率大于小于sylUpdown="+sylUpdown+";市盈率值syl="+syl
		); 
		//1.列出所有个股 ,按照ID升序排序
		String sql=null;
		List<TbStoStock> stockList=null;

		sql="from TbStoStock order by id asc";
		stockList=stockService.findByHql(sql); 
		
		
		//2.得到参数里，开始、结束日期的股价list，并计算多少符合上涨、下跌的放进resultStockList
		List<StoStockdailyDTO > dailyList1=dailyService.queryStoStockdailyByDate(DateFormatUtils.convertStringToDate(startDate), 0, 0,1); 
		List<StoStockdailyDTO > dailyList2=dailyService.queryStoStockdailyByDate(DateFormatUtils.convertStringToDate(endDate), 0, 0, 1); 
		List<TbStoStockdaily> startDailyList=new ArrayList<TbStoStockdaily>();
		List<TbStoStockdaily> endDailyList=new ArrayList<TbStoStockdaily>();
		if (dailyList1!=null && dailyList1.size()>0) {
			Date date =dailyList1.get(0).getOperateDate();   
			startDailyList=dailyService.findByProperty("from TbStoStockdaily where operateDate=?",date);
		}
		if (dailyList2!=null && dailyList2.size()>0) {
			Date date =dailyList2.get(0).getOperateDate();    
			endDailyList=dailyService.findByProperty("from TbStoStockdaily where operateDate=?",date);
		}
		HashMap<Integer, TbStoStockdaily> endMap=new HashMap<Integer, TbStoStockdaily>(); 
		for (TbStoStockdaily tbStoStockdaily : endDailyList) { 
			endMap.put(tbStoStockdaily.getTbStoStock().getId(), tbStoStockdaily);
		}
		List<StoStockDTO> resultStockList=new ArrayList<StoStockDTO>();
		HashMap<Integer, TbStoStock> stockMap=new HashMap<Integer, TbStoStock>();  
		for (TbStoStock tbStoStock : stockList) {
			stockMap.put(tbStoStock.getId(), tbStoStock);
		}
		System.out.println("开始的List size="+startDailyList.size()+";结束List size="+endDailyList.size()); 
		//股票ID，股票价格波动（百分比，比如20.5则为20.5%）
		priceFloatMap=new HashMap<Integer, Double>();
		for (TbStoStockdaily tbStoStockdaily : startDailyList) { 
			if (endMap.get(tbStoStockdaily.getTbStoStock().getId())!=null) { 
				TbStoStockdaily endTbStoStockdaily=endMap.get(tbStoStockdaily.getTbStoStock().getId());
				double temp=(endTbStoStockdaily.getEndPrice()-tbStoStockdaily.getEndPrice())*100/tbStoStockdaily.getEndPrice();
				if (assistDto.getUpdown()==1) {
					//上涨
					if (temp>Double.valueOf(pageRate)) { 
						int stockID=tbStoStockdaily.getTbStoStock().getId();
						resultStockList.add(new StoStockDTO(stockMap.get(stockID)));
//						System.out.println("temp="+temp+";pageRate="+pageRate); 
						priceFloatMap.put(stockID, temp);
					}
				}else {
					if (temp<Double.valueOf(pageRate) && temp>0) {
						int stockID=tbStoStockdaily.getTbStoStock().getId();
						resultStockList.add(new StoStockDTO(stockMap.get(stockID)));
						priceFloatMap.put(stockID, temp);
					}
				}
			}
		} 
		System.out.println("符合股票波动范围的size="+resultStockList.size()+" priceFloatMap size="+priceFloatMap.size()); 
		//3.得到所有个股的总股本,按照股票的ID升序排序（tbStoStock的ID即为股票ID）,并封装进一个map<股票ID，股票总股本>
		List<TbStoCapitalization> capitalizationList=capitalizationService.findByHql("from TbStoCapitalization group by tbStoStock order by tbStoStock asc");
		HashMap<Integer, Double> capitalMap=new HashMap<Integer, Double>();
		for (TbStoCapitalization tbStoCapitalization : capitalizationList) {
			capitalMap.put(tbStoCapitalization.getTbStoStock().getId(), tbStoCapitalization.getTotalCaptial()); 
		}
		
		//4.得到最新的日线数据,按照股票的ID升序排序（tbStoStock的ID即为股票ID）,并封装进一个map<股票ID，日线数据对象>
		Date lastOperateDate=dailyService.findLastDate(); 
		List<TbStoStockdaily> lastDailyList=null; 
		HashMap<Integer, Double> lastDailyMap=new HashMap<Integer, Double>();
		if (lastOperateDate!=null) {
			String lastOperate=DateFormatUtils.convertDateToString(lastOperateDate);
			lastDailyList=dailyService.findByHql("from TbStoStockdaily where operateDate='"+lastOperate+"' order by tbStoStock asc");
		}
		System.out.println("最新的日线数据个数="+(lastDailyList==null?0:lastDailyList.size()));
		for (TbStoStockdaily tbStoStockdaily : lastDailyList) {
			lastDailyMap.put(tbStoStockdaily.getTbStoStock().getId(), tbStoStockdaily.getEndPrice());
		}
		
		
		//5.得到净利润
		Date lastDate=financeProfitService.findLastDate();
		lastDate=DateFormatUtils.convertStringToDate("2009-12-31"); 
		String fieldDate=DateFormatUtils.convertDateToString(lastDate);
		System.out.println("最新日期："+fieldDate); 
		
		//某股的年净利润Map<某股ID，年净利润>
		HashMap<Integer, Double> netGainResultMap=new HashMap<Integer, Double>();
		
		List<TbStoFinanceprofit> oneList=null;
		int iSyl=Integer.valueOf(sylType);
		oneList=financeProfitService.findByHql("from TbStoFinanceprofit where fieldDate ='"+fieldDate+"' order by tbStoStock asc");
		HashMap<Integer, Double> netGainMap1=new HashMap<Integer, Double>(); 
		
		//计算1年的平均净利润，即动态近利润（某个季度乘以季度数）
		
		int month=lastDate.getMonth();
		if (month>=3 && month<6) {
			//已经有第1季度
			for (TbStoFinanceprofit tbStoFinanceprofit : oneList) {
				double netGain=tbStoFinanceprofit.getNetGain();
				netGain=netGain*4;
				int stockId=tbStoFinanceprofit.getTbStoStock().getId();
				netGainMap1.put(stockId,netGain);
			}
		}else if (month>=6 && month<9) {
			//已经有第2季度,半年
			for (TbStoFinanceprofit tbStoFinanceprofit : oneList) {
				double netGain=tbStoFinanceprofit.getNetGain();
				netGain=netGain*2;
				int stockId=tbStoFinanceprofit.getTbStoStock().getId();
				netGainMap1.put(stockId,netGain);
			}
		}else if (month>=9 && month<12) {
			//已经有第3季度
			for (TbStoFinanceprofit tbStoFinanceprofit : oneList) {
				double netGain=tbStoFinanceprofit.getNetGain();
				netGain=(netGain*4)/3;
				int stockId=tbStoFinanceprofit.getTbStoStock().getId();
				netGainMap1.put(stockId,netGain);
			}
		}else {
			//12月份，也就是全年的
			for (TbStoFinanceprofit tbStoFinanceprofit : oneList) {
				double netGain=tbStoFinanceprofit.getNetGain();
				int stockId=tbStoFinanceprofit.getTbStoStock().getId();
				netGainMap1.put(stockId,netGain);
			}
		}
		
		if (0==iSyl || 1==iSyl ) {
			//每个股票的第一年的平均净利润Map<某股ID，第一年净利润>
			netGainResultMap=netGainMap1;
		}else if (iSyl>=2) {
			//计算2或3年的平均净利润
			fieldDate=String.valueOf(lastDate.getYear()-1+1900)+fieldDate.substring(fieldDate.indexOf("-")); 
			String sql2="from TbStoFinanceprofit where fieldDate ='" +fieldDate	+"' order by tbStoStock asc";
			List<TbStoFinanceprofit> twoList=financeProfitService.findByHql(sql2); 
			
			if (iSyl==2) {
				//计算2年的平均净利润
				for (TbStoFinanceprofit tbStoFinanceprofit : twoList) {
					//第二年的净利润
					double netGain=tbStoFinanceprofit.getNetGain();
					int stockId=tbStoFinanceprofit.getTbStoStock().getId();
					//（第二年+第一年的）/2
					if (null==netGainMap1.get(stockId)) {
						continue;
					}
					netGain=(netGain+netGainMap1.get(stockId))/2;
					netGainResultMap.put(stockId,netGain);
				}
				System.out.println("计算2年的平均净利润===netGainMap1.size()="+netGainMap1.size()
						+"list size="+twoList.size()+"最终符合净利润的大小="+netGainResultMap.size());
			}else if(3==iSyl){
				//计算3年的平均净利润
				HashMap<Integer, Double> netGainMap2=new HashMap<Integer, Double>();
				for (TbStoFinanceprofit tbStoFinanceprofit : twoList) { 
					int stockId=tbStoFinanceprofit.getTbStoStock().getId();
					netGainMap2.put(stockId, tbStoFinanceprofit.getNetGain());
				}
				fieldDate=String.valueOf(lastDate.getYear()-2+1900)+fieldDate.substring(fieldDate.indexOf("-")); 
				String sql3="from TbStoFinanceprofit where fieldDate ='" +fieldDate +"' order by tbStoStock asc";
				List<TbStoFinanceprofit> threeList=financeProfitService.findByHql(sql3);
				for (TbStoFinanceprofit tbStoFinanceprofit : threeList) { 
					//第3年的净利润
					double netGain=tbStoFinanceprofit.getNetGain();
					//（第3年+第2年的+第1年的）/3
					int stockId=tbStoFinanceprofit.getTbStoStock().getId();
					if (null ==netGainMap2.get(stockId) || null==netGainMap1.get(stockId) ) {
						continue; 
					}
					netGain=(netGain+netGainMap2.get(stockId)+netGainMap1.get(stockId))/3;
					
					netGainResultMap.put(stockId, tbStoFinanceprofit.getNetGain());
				}
			}
		}
	
		//6.得到市盈率=（现价*总股本）/净利润
		//市盈率的map<股票ID，市盈率大小>
		sylMap=new HashMap<Integer, Double>();
		finalStockList=new ArrayList<StoStockDTO>();
		int iSylUpdown=Integer.valueOf(sylUpdown);
		double dSyl=Double.valueOf(syl);
		
		for (StoStockDTO stockDTO : resultStockList) {
			int stockId=stockDTO.getId();
			//不是所需板块,也不是所有则代表，不是需要的板块
			if (stockType.equals("上海")) {  
				if (!stockDTO.getStockType().contains("上海")) {  
					 priceFloatMap.remove(stockDTO.getId());
					continue;
				}
			} else if (stockType.equals("深圳")) { 
				if (!stockDTO.getStockType().contains("深圳")) { 
					 priceFloatMap.remove(stockDTO.getId());
					continue;
				}
			}else if (stockType.equals("创业板")) { 
				if (!(stockDTO.getStockCode().indexOf("300")==1)) {  
					 priceFloatMap.remove(stockDTO.getId());
					continue; 
				}
			}
			if (capitalMap.get(stockId)==null || lastDailyMap.get(stockId)==null || netGainResultMap.get(stockId)==null) {
//				System.out.println(capitalMap.get(stockId)+";-"+lastDailyMap.get(stockId)+";-"+netGainResultMap.get(stockId)+";capitalMap,lastDailyMap,netGainResultMap==null");
				priceFloatMap.remove(stockDTO.getId());
				continue;
			}else {
				double netgain=netGainResultMap.get(stockId);
				double cap=capitalMap.get(stockId); 
				if (netgain<=0 || cap<=0 || lastDailyMap.get(stockId)<=0) {
					 priceFloatMap.remove(stockDTO.getId());
					 continue;
				}
				double sylNo=(lastDailyMap.get(stockId)*cap)/netgain;
//				System.out.println(stockId+"市盈率大小="+sylNo+"daily="+lastDailyMap.get(stockId)+"cap="+cap+"netgain="+netgain); 
				if (1==iSylUpdown) {
					if (sylNo>=dSyl) {
						//市盈率大于
						finalStockList.add(stockDTO);
						sylMap.put(stockId, sylNo);
					}else {
						priceFloatMap.remove(stockDTO.getId());
						continue;
					}
				}else {
					if (sylNo<=dSyl && sylNo>0) {
						//市盈率小于
						finalStockList.add(stockDTO);
						sylMap.put(stockId, sylNo);
					}else {
						priceFloatMap.remove(stockDTO.getId());
						continue;
					}
				}
			}
		}
		System.out.println("最终结果个数="+finalStockList.size()+" priceFloatMap size="+priceFloatMap.size()); 
		pageStockList=new ArrayList<StoStockDTO>();
		pageSylMap=new TreeMap<Integer, Double>();
		pagePriceFloatMap=new TreeMap<Integer, Double>();
		assistDto=new AssistDto();
		//总数
		int num=finalStockList.size();
		int size=num>limit?limit:num;
		for (int i=0;i<size;i++) {
			StoStockDTO stockDTO=finalStockList.get(i);
			pageStockList.add(stockDTO);
			int stockID=stockDTO.getId();
			DecimalFormat dFormat=new DecimalFormat("0.00");
			pageSylMap.put(stockID,Double.valueOf(dFormat.format(sylMap.get(stockID) )));  
			pagePriceFloatMap.put(stockID,Double.valueOf(dFormat.format(priceFloatMap.get(stockID))));
		}
		assistDto.setCurrentPages(1);
		/**
		 * 总共多少页
		 */
		int totalPages = (num / limit);
		System.out.println("总共多少页totalpages="+totalPages+" num="+num+" limit="+limit); 
		if (num % limit > 0) {
			totalPages++;
		}
	
		assistDto.setTotalPages(totalPages);
		return "success";
	}
	
	public String advSearchPages() throws Exception{
		pageStockList=new ArrayList<StoStockDTO>();
		//总数
		if (0 >= assistDto.getCurrentPages()) {
			assistDto.setCurrentPages(1);
		}
		int num=finalStockList.size(); 
		int size=num-(assistDto.getCurrentPages()-1)*limit;
		if (size<0) {
			size=-size;
		}
		size=size>limit?limit:size;
		int offset = (assistDto.getCurrentPages() -1) * limit;
		for (int i=0;i<size;i++) {
			StoStockDTO stockDTO=finalStockList.get(i+offset);
			pageStockList.add(stockDTO);
			int stockID=stockDTO.getId();
			DecimalFormat dFormat=new DecimalFormat("0.000");
			pageSylMap.put(stockID,Double.valueOf(dFormat.format(sylMap.get(stockID) )));  
			pagePriceFloatMap.put(stockID,Double.valueOf(dFormat.format(priceFloatMap.get(stockID))));
		}
		/**
		 * 总共多少页
		 */
		int totalPages = (num / limit);
		
		if (num % limit > 0) {
			totalPages++;
		}
		assistDto.setTotalPages(totalPages);
		return "success";
	}
	public String sortByPriceFloat() throws Exception{
		if (pagePriceSort==null) {
			pagePriceSort=String.valueOf(1);
		}
		final int sortType=Integer.valueOf(pagePriceSort);
		HashMap<Integer, StoStockDTO> map=new HashMap<Integer, StoStockDTO>();
		for (int i=0;finalStockList!=null && i<finalStockList.size();i++) {
			StoStockDTO stockDTO=finalStockList.get(i);
			 map.put(stockDTO.getId(), stockDTO);
		}
		List<StoStockDTO> tempList=new ArrayList<StoStockDTO>();
		ArrayList<Entry<Integer, Double>> l = new ArrayList<Entry<Integer, Double>>(
				priceFloatMap.entrySet());
		Collections.sort(l, new Comparator<Map.Entry<Integer, Double>>() {
			
			public int compare(Map.Entry<Integer, Double> o1,
					Map.Entry<Integer, Double> o2) {
				BigDecimal   i1 =new BigDecimal(o1.getValue()); 
				BigDecimal   i2 =new BigDecimal(o2.getValue()); 
				int result ; 
				result=i2.compareTo(i1);
				if (0==sortType) {
					result=-result;
				}
				return result;
			}
		});
		for (Entry<Integer, Double> entry : l) {
			 tempList.add(map.get(entry.getKey())); 
		}
		finalStockList=tempList;
		assistDto.setCurrentPages(1);
		pageSylSort=String.valueOf(2);
		this.advSearchPages();
		return "list";
	}
	
	public String sortBySyl() throws Exception{
		if (pageSylSort==null) {
			pageSylSort=String.valueOf(1);
		}
		final int sortType=Integer.valueOf(pageSylSort);
		HashMap<Integer, StoStockDTO> map=new HashMap<Integer, StoStockDTO>();
		for (StoStockDTO stockDTO : finalStockList) {
			 map.put(stockDTO.getId(), stockDTO);
		}
		List<StoStockDTO> tempList=new ArrayList<StoStockDTO>();
		ArrayList<Entry<Integer, Double>> l = new ArrayList<Entry<Integer, Double>>(
				sylMap.entrySet());
		Collections.sort(l, new Comparator<Map.Entry<Integer, Double>>() {
			
			public int compare(Map.Entry<Integer, Double> o1,
					Map.Entry<Integer, Double> o2) {
				BigDecimal   i1 =new BigDecimal(o1.getValue()); 
				BigDecimal   i2 =new BigDecimal(o2.getValue()); 
				int result ; 
				result=i2.compareTo(i1);
				if (0==sortType) {
					result=-result;
				}
				return result;
			}
		});
		for (Entry<Integer, Double> entry : l) {
			 tempList.add(map.get(entry.getKey())); 
		}
		finalStockList=tempList;
		assistDto.setCurrentPages(1);
		pagePriceSort=String.valueOf(2);
		this.advSearchPages();
		return "list";
	}
	
	
	
	public AssistDto getAssistDto() {
		return assistDto;
	}

	public void setAssistDto(AssistDto assistDto) {
		this.assistDto = assistDto;
	}

	public String getStockType() {
		return stockType;
	}

	public void setStockType(String stockType) {
		this.stockType = stockType;
	}

	public String getSylType() {
		return sylType;
	}

	public void setSylType(String sylType) {
		this.sylType = sylType;
	}

	public String getSylUpdown() {
		return sylUpdown;
	}

	public void setSylUpdown(String sylUpdown) {
		this.sylUpdown = sylUpdown;
	}

	public String getSyl() {
		return syl;
	}

	public void setSyl(String syl) {
		this.syl = syl;
	}

	public StoStockdailyService getDailyService() {
		return dailyService;
	}

	public void setDailyService(StoStockdailyService dailyService) {
		this.dailyService = dailyService;
	}

	public StoStockService getStockService() {
		return stockService;
	}

	public void setStockService(StoStockService stockService) {
		this.stockService = stockService;
	}

	public StoFinanceProfitService getFinanceProfitService() {
		return financeProfitService;
	}

	public void setFinanceProfitService(StoFinanceProfitService financeProfitService) {
		this.financeProfitService = financeProfitService;
	}

	public StoCapitalizationService getCapitalizationService() {
		return capitalizationService;
	}

	public void setCapitalizationService(
			StoCapitalizationService capitalizationService) {
		this.capitalizationService = capitalizationService;
	}

	public List<StoStockDTO> getPageStockList() {
		return pageStockList;
	}

	public void setPageStockList(List<StoStockDTO> pageStockList) {
		this.pageStockList = pageStockList;
	}


	public TreeMap<Integer, Double> getPagePriceFloatMap() {
		return pagePriceFloatMap;
	}

	public void setPagePriceFloatMap(TreeMap<Integer, Double> pagePriceFloatMap) {
		this.pagePriceFloatMap = pagePriceFloatMap;
	}

	public TreeMap<Integer, Double> getPageSylMap() {
		return pageSylMap;
	}

	public void setPageSylMap(TreeMap<Integer, Double> pageSylMap) {
		this.pageSylMap = pageSylMap;
	}

	@Override
	public AssistDto getModel() {
		if (assistDto==null) {
			assistDto=new AssistDto();
		}
		return assistDto;
	}
	

	public List<StoStockDTO> getFinalStockList() {
		return finalStockList;
	}

	public void setFinalStockList(List<StoStockDTO> finalStockList) {
		this.finalStockList = finalStockList;
	}
	

	public HashMap<Integer, Double> getSylMap() {
		return sylMap;
	}

	public void setSylMap(HashMap<Integer, Double> sylMap) {
		this.sylMap = sylMap;
	}

	public HashMap<Integer, Double> getPriceFloatMap() {
		return priceFloatMap;
	}

	public void setPriceFloatMap(HashMap<Integer, Double> priceFloatMap) {
		this.priceFloatMap = priceFloatMap;
	}

	public String getPageStartDate() {
		return pageStartDate;
	}

	public void setPageStartDate(String pageStartDate) {
		this.pageStartDate = pageStartDate;
	}

	public String getPageEndDate() {
		return pageEndDate;
	}

	public void setPageEndDate(String pageEndDate) {
		this.pageEndDate = pageEndDate;
	}

	public String getPageRate() {
		return pageRate;
	}

	public void setPageRate(String pageRate) {
		this.pageRate = pageRate;
	}

	public String getPagePriceSort() {
		return pagePriceSort;
	}

	public void setPagePriceSort(String pagePriceSort) {
		this.pagePriceSort = pagePriceSort;
	}

	public String getPageSylSort() {
		return pageSylSort;
	}

	public void setPageSylSort(String pageSylSort) {
		this.pageSylSort = pageSylSort;
	}
	
}
